BERT 全名為 Bidirectional Encoder Representations From Transformers,翻譯成中文其實就是雙向 Transformer 的 Encoder。那麼,BERT 可以拿來做什麼?我們又為何會提到他呢?
PS:接下來介紹的圖片教材來源皆為台大李宏毅教授的 BERT 教學,有興趣的話可以去聽詳細內容,相信一定能有所收穫。
我們剛才說了,BERT 的架構是 Transformer 的 Encoder。還記得 Encoder 做的事情嗎?就是將我們 input 的序列資料轉換成向量,之後再由 Decoder 讀取該向量的資訊後產生 output 。
因此, BERT 在做的事情就是透過一層又一層的 Self-Attention layer 去關注、學習每一個輸入的向量後,輸出另一串向量。而我們便能夠從輸出的向量中取需要的部份,丟進其他模型或者分類器中來完成自己想要做的任務(這一階段我們稱呼為 Fine-Tuning(微調))。
我們為什麼會提到 BERT 呢?這裡就必須先提一下過去我們在處理自然語言處理(NLP)任務時所會面臨的困境:
訓練數據不好取得。
假設今天我們想要做翻譯任務,我們花了千辛萬苦的收集了大約十萬篇文章;每篇文章起碼1000字以上。我們想要用該資料集對模型進行訓練卻很有可能訓練不起來。因為要同時理解A、B兩種不同語言的語意並將雙方的知識對應在一起本來就是一件超級困難的事情。只憑十萬筆資料就想學會2種語言並融會貫通根本是痴人說夢。
缺乏通用架構
假設我們真的克服了訓練數據的問題並且成功的設計出了一個將A語言翻譯成B語言的模型,其結構通常也是專門為了完成該任務來進行設計的。不同的自然語言任務通常需要不同的模型,而重新設計一個模型並進行測試是非常累人的。
而 BERT 的強大之處就在於它的訓練資料可以直接從無標記文本中直接取得!它的預訓練資料包含了大量來自 Wikipedia(25億字)、 BooksCorpus(8億字) 等未經標籤的文本資料。運用的方式很簡單,就是讓它去預測下一個字就行了!就像是我們在日常生活中看過、寫過越多文章,對於一個語言的知識累積就會越來越深一樣。而當模型已經具備了很多語言的知識、常識後,訓練起來是不是就容易多了呢?
正因如此, BERT的架構還只需要先訓練好一個之後,就可以套用到其他自然語言任務中!並且在眾多自然語言處理的任務中都有良好的表現。
(因為它已經學會一種語言了,我們自然能將它套用在不同的任務中,不過還是需要視任務情況對後續進行微調啦)
BERT 的使用分為兩大步驟: Pre-training(預訓練) 與 Fine-Tuning(微調)。
在 Pre-training 階段,BERT 會接收大量文本資料,然後以非監督式學習的方式開始訓練模型。然後當我們的模型對自然語言理解到一定程度後,我們就可以進入 Fine-Tuning 階段了。
在 Fine-Tuning 階段,我們會針對不同的任務,使用有標籤的資料對模型進行訓練、微調。像是把文本進行切分、層數選擇、調整學習率...等。
在 Pre-training(預訓練)階段,BERT主要使用2種方法進行訓練,分別是:
首先是 Masked language model,簡稱為 Mask LM。輸入的辭彙中有15%的機率被替換成 [Mask] 的 token,而 BERT 要做的便是填回被蓋住的辭彙。(其實就是克漏字啦)
將挖空部份的embedding丟進一個線性的多分類器中,並要求這個線性的分類器去預測這個被挖空的辭彙
例如圖中的範例,首先我們照常將輸入通過 BERT 後,我們會將[MASK]位置的輸出丟進一個線性的多分類器內,然後要求這個線性的分類器去預測被遮住的辭彙『退了』二字才行。
PS:一般在做 BERT 中文訓練時,用"字"來訓練可能比用"詞"訓練更為恰當。因為中文的"字"是有限的,但"詞"的組合卻是成千上萬。
再來是下一句預測 (Next Sentence Prediction),其實就是讓 BERT 去預測下一個句子接在上一個句子後面是否合理。例如圖中的句子,一個是"醒醒吧",另一個是"你沒有妹妹",我們會希望 BERT 也能準確的預測說這兩個句子是接在一起的。
而為了讓BERT預測兩個句子是否相接,我們還必須引入一些特殊的符號:[SEP]是用來告訴BERT這次句子的交界處;而[CLS]則是放在句子起始處,用來告訴BERT接下來在這個位置要做分類,並將該位置的輸出放進一個線性的二元分類器,再由該分類器輸出這兩個句子是否相接的結果。
PS:另外由於 Encoder 內部採用 Self-Attention 的關係,[CLS]不管是放在頭還是尾其實是影響不大的。
BERT 的原論文有提出4種不同的 BERT 應用情境:
首先是第一種:句子分類判斷。例如情緒分析,或是文章分類...等。
作法是將想要分類的句子輸入 BERT 後,開頭的地方再加一個代表分類的符號[CLS]。接下來再將該符號位置的輸出丟給一個線性分類器,並由這個線性分類器去預測這個句子類別,而訓練時我們只要微調 BERT 並訓練分類器即可。
第二個任務是將句子中每個詞的分類:輸入一個句子,而句子裡的每一個辭彙都要決定屬於哪一個類別,例如 slot-filling。
而 BERT 的作法就是先輸入一個句子,再將每個辭彙的輸出都丟入線性分類器裡面,讓他去決定這個辭彙的所屬類別。
第三種用法則是判斷句子關係:輸入2個句子 然後輸出一個類別。例如 natural language inference(自然語言推理),要機器學會推論一句話,就是先給機器一個前提與架設,然後要機器根據前提與假設去推論對錯,或者不知道。
如圖中所示,先輸入2個句子,然後在句子的起始處與相接處放入特殊符號[SEP],再將開頭處的輸出丟給線性分類器去判斷 True/False 或者 unknown。
最後則是文章問答提取最佳解:大致上就是輸入一篇文章,提出問題後再找出解答。
例如圖中的問題,我們給定了文章 D 與問題 Q ,那我們有一個 QA model,而這個 QA model 就是輸入一篇文章跟一個問題,然後輸出2個整數 s 跟 e;而 s 與 e 代表現在答案落在文章的第 s 個辭彙~第 e 個辭彙中。假設圖片中第一個答案為 gravity,而他是這篇文章中第17個字,則輸出 s=17,e=17 答案就是 gravity。那這個問題套用到 BERT 要怎麼做呢?
而紅色的向量決定了 s 是多少,那藍色的向量則決定了 e 是多少。
同樣的方法,將藍色的向量與黃色的向量做內積,然後再透過Softmax 看誰算出的分數最高,例如圖中第三個詞彙算出來的詞彙最高,則 e = 3。
那 s=2、e=3 就代表答案為文章的第2,第3個字,也就是"d2d3"。
那假設今天輸出的是 s=3、e=2 的話就互相矛盾,則模型會輸出此題無解。而橘色的向量跟藍色的向量其實都是學出來的(與昨天介紹的 Self-Attention 內的 Query 、 Key 、 Value 一樣),因此在訓練的時候需要給機器很多的問題、文章跟答案坐落的地點來讓機器去進行學習才行。